import { ArrayType, EPSILON } from "./common";
/**
 * 四维向量类
 * @class
 * @author jsbrml
 */
class Vec4 extends ArrayType {
    /**
     * 构造函数。
     * @constructor
     */
    constructor(element = [0, 0, 0, 0]) {
        super(element);
    }
    /**
     * @property  {Number} x 
     * 【读写】获取向量的x分量。
     */
    get x() {
        return this[0];
    }
    set x(v) {
        this[0] = v;
    }
    /**
     * @property  {Number} y 
     * 【读写】获取向量的y分量。
     */
    get y() {
        return this[1];
    }
    set y(v) {
        this[1] = v;
    }
    /**
     * @property  {Number} z 
     * 【读写】获取向量的z分量。
     */
    get z() {
        return this[2];
    }
    set z(v) {
        this[2] = v;
    }
    /**
     * @property  {Number} w
     * 【读写】获取向量的w分量。
     */
    get w() {
        return this[3];
    }
    set w(v) {
        this[3] = v;
    }
    /**
     * 向量对象转化为字符串。
     * @method
     */
    toString() {
        return `Vec4(${this.join(',')})`
    }
    /**
     * 向量拷贝。
     * @method
     */
    copy(v) {
        this[0] = v[0];
        this[1] = v[1];
        this[2] = v[2];
        this[3] = v[3];
        return this;
    }
    /**
     * 当前向量和目标向量是否相等。
     * @method
     */
    equal(v) {
        return (Math.abs(this[0] - v[0]) <= EPSILON) && (Math.abs(this[1] - v[1]) <= EPSILON) && (Math.abs(this[2] - v[2]) <= EPSILON) && (Math.abs(this[3] - v[3]) <= EPSILON);
    }
    /**
     * 向量克隆。
     * @method
     */
    clone() {
        return new Vec4(this);
    }
    /**
     * 向量加法。
     * @method
     */
    add(v) {
        this[0] += v[0];
        this[1] += v[1];
        this[2] += v[2];
        this[3] += v[3];
        return this;
    }
    /**
     * 向量减法。
     * @method
     */
    sub(v) {
        this[0] -= v[0];
        this[1] -= v[1];
        this[2] -= v[2];
        this[3] -= v[3];
        return this;
    }
    /**
     * 向量乘法。
     * @method
     */
    multiply(v) {
        this[0] *= v[0];
        this[1] *= v[1];
        this[2] *= v[2];
        this[3] *= v[3];
        return this;
    }
    /**
     * 向量除法。
     * @method
     */
    div(v) {
        this[0] /= v[0];
        this[1] /= v[1];
        this[2] /= v[2];
        this[3] /= v[3];
        return this;
    }
    /**
     * 向量缩放。
     * @method
     */
    scale(v) {
        this[0] *= v;
        this[1] *= v;
        this[2] *= v;
        this[3] *= v;
        return this;
    }
    /**
     * 向量反向。
     * @method
    */
    negate() {
        this[0] *= -1;
        this[1] *= -1;
        this[2] *= -1;
        this[3] *= -1;
        return this;
    }
    length() {
        return Math.sqrt(this[0] * this[0] + this[1] * this[1] + this[2] * this[2] + this[3] * this[3]);
    }
    distance(v) {
        let x = this[0] - v[0], y = this[1] - v[1], z = this[2] - v[2], w = this[3] - v[3];
        return Math.sqrt(x * x + y * y + z * z + w * w);
    }
    /**
     * 向量插值。
     * @param {Number} t 插值参数，0表示起点 1表示终点
     * @method
     */
    lerp(t) {
        this[0] *= t;
        this[1] *= t;
        this[2] *= t;
        this[3] *= t;
        return this;
    }
    /**
     * 向量的逆。
     * @method
     */
    inverse() {
        this[0] = 1.0 / this[0];
        this[1] = 1.0 / this[1];
        this[2] = 1.0 / this[2];
        this[3] = 1.0 / this[3];
        return this;
    }
    /**
     * 向量的绝对值变换。
     * @method
     */
    abs() {
        this[0] = Math.abs(this[0]);
        this[1] = Math.abs(this[1]);
        this[2] = Math.abs(this[2]);
        this[3] = Math.abs(this[3]);
        return this;
    }
    /**
     * 当前向量和目标向量的点积。
     * @param {Vec4} v 目标向量。
     * @method
     */
    dot(v) {
        return this[0] * v[0] + this[1] * v[1] + this[2] * v[2] + this[3] * v[3];
    }
    /**
     * 叉乘
     * @method
     */
    cross(v, w) {
        let A = v[0] * w[1] - v[1] * w[0],
            B = v[0] * w[2] - v[2] * w[0],
            C = v[0] * w[3] - v[3] * w[0],
            D = v[1] * w[2] - v[2] * w[1],
            E = v[1] * w[3] - v[3] * w[1],
            F = v[2] * w[3] - v[3] * w[2];
        let G = this[0];
        let H = this[1];
        let I = this[2];
        let J = this[3];
        this[0] = H * F - I * E + J * D;
        this[1] = -(G * F) + I * C - J * B;
        this[2] = G * E - H * C + J * A;
        this[3] = -(G * D) + H * B - I * A;
        return this;
    }
    /**
     * 乘4阶矩阵
     * @method
     */
    transformMat4(m) {
        let x = this[0],
            y = this[1],
            z = this[2],
            w = this[3];
        this[0] = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
        this[1] = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
        this[2] = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
        this[3] = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
        return this;
    }
    /**
     * 乘四元数
     * @method
     */
    transformQuat(q) {
        let x = this[0],
            y = this[1],
            z = this[2];
        let qx = q[0],
            qy = q[1],
            qz = q[2],
            qw = q[3];
        // calculate quat * vec
        let ix = qw * x + qy * z - qz * y;
        let iy = qw * y + qz * x - qx * z;
        let iz = qw * z + qx * y - qy * x;
        let iw = -qx * x - qy * y - qz * z;
        // calculate result * inverse quat
        this[0] = ix * qw + iw * -qx + iy * -qz - iz * -qy;
        this[1] = iy * qw + iw * -qy + iz * -qx - ix * -qz;
        this[2] = iz * qw + iw * -qz + ix * -qy - iy * -qx;
        this[3] = this[3];
        return this;
    }
    /**
     * 向量归一化。
     * @method
     */
    normalize() {
        let x = this[0];
        let y = this[1];
        let z = this[2];
        let w = this[3];
        let len = x * x + y * y + z * z + w * w;
        if (len > 0) {
            len = 1 / Math.sqrt(len);
        }
        this[0] = x * len;
        this[1] = y * len;
        this[2] = z * len;
        this[3] = w * len;
        return this;
    }
}
export { Vec4 }